package com.xiaoluo.lottery.common.weixin;

import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Response;
import com.xiaoluo.lottery.common.weixin.auth.IWeiXinAuth;
import com.xiaoluo.lottery.common.weixin.base.BaseRes;
import com.xiaoluo.lottery.common.weixin.hb.IWeiXinHb;
import com.xiaoluo.lottery.common.weixin.hb.beans.HbInfoReq;
import com.xiaoluo.lottery.common.weixin.hb.beans.HbInfoRes;
import com.xiaoluo.lottery.common.weixin.hb.beans.RedPackReq;
import com.xiaoluo.lottery.common.weixin.hb.beans.RedPackRes;
import com.xiaoluo.lottery.common.weixin.msg.IWeiXinMsg;
import com.xiaoluo.lottery.common.weixin.msg.beans.TemplateMsgReq;
import com.xiaoluo.lottery.common.weixin.msg.beans.TemplateMsgRes;
import com.xiaoluo.lottery.common.weixin.pay.IWeiXinPay;
import com.xiaoluo.lottery.common.weixin.pay.beans.*;
import com.xiaoluo.lottery.common.weixin.utils.Configure;
import com.xiaoluo.lottery.common.weixin.utils.SSLUtil;
import com.xiaoluo.lottery.common.weixin.utils.XmlUtil;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import retrofit.ErrorHandler;
import retrofit.RestAdapter;
import retrofit.RetrofitError;
import retrofit.client.OkClient;
import retrofit.converter.JacksonConverter;
import retrofit.converter.SimpleXMLConverter;

import javax.net.ssl.SSLContext;
import java.security.KeyStore;

/**
 * Project : lottery
 * Package : main.java.com.xiaoluo.lottery.common.weixin
 * Created by Willian.
 * Date  : 2016/4/6 13:55.
 */
public class WeiXinClient {
    private final static String AUTH_URL = "http://www.xiaoluo.com/pmsshow";
    private final static String WEI_XIN_PAY_URL = "https://api.mch.weixin.qq.com";
    private final static String WEI_XIN_MSG_URL = "https://api.weixin.qq.com/cgi-bin";


    private static IWeiXinPay weiXinPay;    //微信支付api
    private static IWeiXinPay weiXinPayCert;//微信支付-退款api
    private static IWeiXinHb  weiXinHb;     //微信红包api
    private static IWeiXinAuth weiXinAuth;  //获取WeiXin accessToken api
    private static IWeiXinMsg weiXinMsg;    //微信消息api



    /**
     * 统一下单
     * @param req
     * @return
     * @throws Exception
     */
    public static UnifiedOrderRes unifiedorder(UnifiedOrderReq req) throws Exception{
        return getWeiXinPay().unifiedorder(req.builder(req), getWeiXinAuth().getAccessToken().getAccessToken());
    }

    /**
     * 测试接口
     * @param req
     * @return
     * @throws Exception
     */
    public static UnifiedOrderRes test(TestReq req) throws Exception{
        return getWeiXinPay().test(req, getWeiXinAuth().getAccessToken().getAccessToken());
    }

    /**
     * 查询订单
     * @param req
     * @return
     * @throws Exception
     */

    public static OrderQueryRes orderquery(OrderQueryReq req) throws Exception{
        return getWeiXinPay().orderquery(req.builder(req));
    }

    /**
     * 关闭订单
     * @param req
     * @return
     * @throws Exception
     */
    public static CloseOrderRes closeorder(CloseOrderReq req) throws Exception{
        return getWeiXinPay().closeorder(req.builder(req));
    }


    /**
     * 申请退款
     * 需双向证书
     * @param req
     * @return
     * @throws Exception
     */

    public static RefundRes refund(RefundReq req) throws Exception{
        return getWeiXinPayCertClient().refund(req.builder(req));
    }


    /**
     * 查询退款
     * @param req
     * @return
     * @throws Exception
     */
    public static RefundQueryRes refundquery(RefundQueryReq req) throws Exception{
        return getWeiXinPay().refundquery(req.builder(req));
    }

    /**
     * 测试上报
     * @param req
     * @return
     * @throws Exception
     */
    public static BaseRes report(ReportReq req) throws Exception{
        return getWeiXinPay().report(req.builder(req));
    }

    /**
     * 下载账单
     * @param req
     * @return
     * @throws Exception
     */
    public static Response downloadbill(DownloadBillReq req) throws Exception{
        Response res = getWeiXinPay().downloadbill(req);
        return res;
    }
    /**
     * 付款通知回调请求处理
     * @return
     * @throws Exception
     */
    public static OrderNotifyReq orderNotify(String xml)throws Exception{
        OrderNotifyReq res = (OrderNotifyReq) XmlUtil.getObjectFromXML(xml, OrderNotifyReq.class);
        return res;
    }

    /**
     * 发红包
     * @param req
     * @return
     * @throws Exception
     */
    public static RedPackRes sendHb(RedPackReq req)throws Exception{
        req.builder();
        return getWeiXinHbCertClient().sendredpack(req);
    }

    /**
     * 查询红包
     * @param req
     * @return
     * @throws Exception
     */
    public static HbInfoRes gethbinfo(HbInfoReq req)throws Exception{
        req.setBill_type(Configure.getMCHT());
        return getWeiXinHbCertClient().gethbinfo(req.builder(req));
    }

    /**
     * 发送模板消息
     * @param req
     * @return
     * @throws Exception
     */
    public static TemplateMsgRes sendMsg(TemplateMsgReq req) throws Exception{
        return getWeiXinMsg().sendMsg(req,getWeiXinAuth().getAccessToken().getAccessToken());
    }




    /**
     * 根据证书生成ssl client.
     * @return
     * @throws Exception
     */
    private static IWeiXinPay getWeiXinPayCertClient() throws Exception{

        if(weiXinPayCert == null){
            OkHttpClient client = new OkHttpClient();
            KeyStore keyStore = SSLUtil.readKeyStore(Configure.getCertPassword()); //your method to obtain KeyStore
            // Trust own CA and all self-signed certs
            SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, Configure.getCertPassword().toCharArray()).build();
            // Allow TLSv1 protocol only
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,new String[]{"TLSv1"},null,SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
            client.setSslSocketFactory(sslcontext.getSocketFactory());

            RestAdapter restAdapterCert = new RestAdapter.Builder()
                    .setConverter(new SimpleXMLConverter())
                    .setEndpoint(WEI_XIN_PAY_URL)
                    .setClient(new OkClient(client))
                    .setErrorHandler(new PayErrorHandler())
                    .setLogLevel(RestAdapter.LogLevel.FULL)
                    .build();

            weiXinPayCert = restAdapterCert.create(IWeiXinPay.class);
        }

        return weiXinPayCert;
    }

    /**
     * 红包客户端
     * @return
     * @throws Exception
     */
    private static IWeiXinHb getWeiXinHbCertClient() throws Exception{

        if(weiXinHb == null){
            OkHttpClient client = new OkHttpClient();
            KeyStore keyStore = SSLUtil.readKeyStore(Configure.getCertPassword()); //your method to obtain KeyStore
            // Trust own CA and all self-signed certs
            SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, Configure.getCertPassword().toCharArray()).build();
            // Allow TLSv1 protocol only
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,new String[]{"TLSv1"},null,SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
            client.setSslSocketFactory(sslcontext.getSocketFactory());


            RestAdapter restAdapterCert = new RestAdapter.Builder()
                    .setConverter(new SimpleXMLConverter())
                    .setEndpoint(WEI_XIN_PAY_URL)
                    .setClient(new OkClient(client))
                    .setErrorHandler(new PayErrorHandler())
                    .setLogLevel(RestAdapter.LogLevel.FULL)
                    .build();

            weiXinHb = restAdapterCert.create(IWeiXinHb.class);
        }

        return weiXinHb;
    }

    private static IWeiXinPay getWeiXinPay(){

        if(weiXinAuth == null){
            RestAdapter restAdapter = new RestAdapter.Builder()
                    .setConverter(new SimpleXMLConverter())
                    .setEndpoint(WEI_XIN_PAY_URL)
                    .setErrorHandler(new PayErrorHandler())
                    .setLogLevel(RestAdapter.LogLevel.FULL)
                    .build();

            weiXinPay = restAdapter.create(IWeiXinPay.class);
        }

        return weiXinPay;
    }
    /**
     * 获取accessToken client.
     * @return
     */
    private static IWeiXinAuth getWeiXinAuth(){
        if(weiXinAuth == null){
            RestAdapter restAdapter = new RestAdapter.Builder()
                    .setConverter(new JacksonConverter())
                    .setEndpoint(AUTH_URL)
                    .setErrorHandler(new PayErrorHandler())
                    .setLogLevel(RestAdapter.LogLevel.FULL)
                    .build();

            weiXinAuth = restAdapter.create(IWeiXinAuth.class);
        }
        return weiXinAuth;
    }

    /**
     *
     * @return
     */
    private static IWeiXinMsg getWeiXinMsg(){
        if(weiXinMsg == null){
            RestAdapter restAdapter = new RestAdapter.Builder()
                    .setConverter(new JacksonConverter())
                    .setEndpoint(WEI_XIN_MSG_URL)
                    .setErrorHandler(new PayErrorHandler())
                    .build();

            weiXinMsg = restAdapter.create(IWeiXinMsg.class);
        }
        return weiXinMsg;
    }
    /**
     * 异常处理
     */
    private static final class PayErrorHandler implements ErrorHandler {
        @Override
        public Throwable handleError(final RetrofitError cause) {
            if (cause.getResponse() == null) {
                return cause;
            }
            return (Exception) cause.getBodyAs(Exception.class);
        }
    }

}
